package com.weilele.mvvm.utils.net

import com.weilele.mvvm.okHttpClient
import com.weilele.mvvm.utils.net.gson_adapter.MyGsonConverterFactory
import com.weilele.mvvm.utils.printStackTrace
import okhttp3.OkHttpClient
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit


/**
 * 默认的创建网络的请求，数据会转为Bean
 */
inline fun <reified T> createRetrofitApi(baseUrl: String, client: OkHttpClient = okHttpClient): T {
    return createRetrofitApiWithResultCall<T, Any>(baseUrl, client, null)
}

/**
 * 请求数据，并对结果进行回调
 * 方便统一处理
 */
inline fun <reified T, Bean> createRetrofitApiWithResultCall(
        baseUrl: String, client: OkHttpClient = okHttpClient,
        noinline resultCall: Function3<@ParameterName("result") Bean?,
                @ParameterName("error") Throwable?,
                @ParameterName("originalResult") Any, Unit>?
): T {
    val retrofit = Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(client)
            .addConverterFactory(MyGsonConverterFactory.create(resultCall))
            .build()
    return retrofit.create(T::class.java)
}

/**
 * 有基本的使用功能，需要自定义转换器
 */
inline fun <reified T> createCustomRetrofitApi(
        baseUrl: String,
        noinline builder: ((Retrofit.Builder) -> Unit)? = null): T {
    val retrofitBuilder = Retrofit.Builder()
    retrofitBuilder.baseUrl(baseUrl)
    builder?.invoke(retrofitBuilder)
    return retrofitBuilder.build().create(T::class.java)
}

/**
 * 通过service发送请求，并回调
 */
fun <T> retrofit2.Call<T>.sendAsync(success: (T) -> Unit, fail: ((Throwable?) -> Unit)? = null) {
    enqueue(object : Callback<T> {
        override fun onFailure(call: retrofit2.Call<T>?, t: Throwable?) {
            fail?.invoke(t)
            printStackTrace { t }
        }

        override fun onResponse(call: retrofit2.Call<T>?, response: Response<T>?) {
            val body = response?.body()
            if (body == null) {
                fail?.invoke(Throwable("response.body is null"))
            } else {
                success.invoke(body)
            }
        }
    })
}

fun <T> retrofit2.Call<T>.sendAsync(callback: Callback<T>) {
    enqueue(callback)
}

fun <T> retrofit2.Call<T>.sendAwait(): Response<T> {
    return execute()
}
